package priv.pfz.raft.peer;

import lombok.Getter;
import lombok.Setter;

import java.text.MessageFormat;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

import static java.util.concurrent.TimeUnit.NANOSECONDS;

/**
 * @author pengfangzhou
 * @date 2022/2/6 19:00
 */
@Getter
@Setter
public class RaftEvent implements Delayed {
    private final String name;
    private final Runnable runnable;
    private final long effectTime;
    private final int version;

    //for freezing
    private long leftTime;
    private boolean pausing = false;

    public RaftEvent(String name, Runnable runnable, long effectTime, int version) {
        this.name = name;
        this.runnable = runnable;
        this.effectTime = effectTime;
        this.version = version;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(effectTime - System.nanoTime(), NANOSECONDS);
    }

    @Override
    public int compareTo(Delayed other) {
        if (other == this) // compare zero if same object
            return 0;
        if (other instanceof RaftEvent) {
            RaftEvent x = (RaftEvent) other;
            long diff = effectTime - x.effectTime;
            if (diff < 0)
                return -1;
            else if (diff > 0)
                return 1;
            else
                return 1;
        }
        long diff = getDelay(NANOSECONDS) - other.getDelay(NANOSECONDS);
        return (diff < 0) ? -1 : (diff > 0) ? 1 : 0;
    }

    @Override
    public String toString() {
        long leftMillis = TimeUnit.NANOSECONDS.toMillis(pausing ? leftTime : (effectTime - System.nanoTime()));
        return MessageFormat.format("{0}(left {1} ms)", name, leftMillis);
    }
}
